# @File: http_client.py
# -*- coding: utf-8 -*-
# __author:"super"
# @time:2025/7/25 13:46
from contextlib import contextmanager
from copy import deepcopy
from functools import partial
from tools.storage import cache
import requests
from typing import List, Type, Callable, Any

from .middlewares.registry import registry, init_middlewares, MiddlewareCallable, RequestType, ResponseType

"""
HTTP 客户端模块，负责发送 HTTP 请求和处理响应
1.CachedResponse 类:包装原始的 requests.Response 对象，提供缓存功能
2.HTTPClient 类: 使用 requests.Session() 创建会话
3.全局客户端管理:get_http_client() 函数提供单例模式的 HTTP 客户
"""


class CachedResponse:
    def __init__(self, raw_response: requests.Response):
        self.raw_response = raw_response
        self._cached_json = None

    def __getattr__(self, name):
        return getattr(self.raw_response, name)

    def json(self, **kwargs) -> Any:
        if self._cached_json is None:
            self._cached_json = self.raw_response.json(**kwargs)
        return self._cached_json


class HTTPClient:
    def __init__(self, middlewares: List[MiddlewareCallable] = None):
        self.session = requests.Session()
        init_middlewares()
        self.middlewares = registry.active_middlewares
        if middlewares:
            self.middlewares.extend(middlewares)

    def send_request(self, request: RequestType, override_headers: bool = False, **kwargs) -> ResponseType:
        if override_headers:
            final_headers = request.get("headers", {})
        else:
            final_headers = {**self.session.headers, **request.get("headers", {})}

        merged_request = {**request, **kwargs, "headers": final_headers}

        def send(req: RequestType) -> ResponseType:
            req.pop("_api_meta")
            raw_response = self.session.request(**req)
            return CachedResponse(raw_response)

        call_next = send
        for middleware in reversed(self.middlewares):
            call_next = partial(middleware, call_next=call_next)

        return call_next(merged_request)

    @contextmanager
    def headers_override_scope(self, headers: dict):
        """上下文管理器：临时完全替换请求头"""
        original_headers = deepcopy(self.session.headers)
        try:
            self.session.headers.clear()
            self.session.headers.update(headers)
            yield
        finally:
            self.session.headers = original_headers


def get_http_client(default_client: Type[HTTPClient]) -> HTTPClient:
    if not hasattr(get_http_client, "client"):
        get_http_client.client = default_client()
        headers = cache.get("headers")
        get_http_client.client.session.headers.update(headers)
    return get_http_client.client
